package cn.iocoder.yudao.module.call.service.ivrvoice;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.module.call.controller.admin.ivrflow.vo.IvrFlowNodeVO;
import cn.iocoder.yudao.module.call.dal.dataobject.ivrflow.IvrFlowDO;
import cn.iocoder.yudao.module.call.dal.dataobject.ivrrobottimbre.IvrRobotTimbreDO;
import cn.iocoder.yudao.module.call.dal.dataobject.ivrtimbre.IvrTimbreDO;
import cn.iocoder.yudao.module.call.dal.mysql.ivrflow.IvrFlowMapper;
import cn.iocoder.yudao.module.call.dal.mysql.ivrrobottimbre.IvrRobotTimbreMapper;
import cn.iocoder.yudao.module.call.dal.mysql.ivrtimbre.IvrTimbreMapper;
import cn.iocoder.yudao.module.call.util.TmtUtil;
import cn.iocoder.yudao.module.call.util.TtsHuoShanUtil;
import cn.iocoder.yudao.module.call.util.TtsUtil;
import cn.iocoder.yudao.module.infra.api.file.FileApi;
import cn.iocoder.yudao.module.system.api.extend.ExtendApi;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;

import org.springframework.validation.annotation.Validated;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;

import cn.iocoder.yudao.module.call.controller.admin.ivrvoice.vo.*;
import cn.iocoder.yudao.module.call.dal.dataobject.ivrvoice.IvrVoiceDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;

import cn.iocoder.yudao.module.call.dal.mysql.ivrvoice.IvrVoiceMapper;
import org.springframework.web.multipart.MultipartFile;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.call.enums.ErrorCodeConstants.*;

/**
 * ivr-语音 Service 实现类
 *
 * @author 数创万维
 */
@Service
@Validated
public class IvrVoiceServiceImpl implements IvrVoiceService {

    @Resource
    private IvrVoiceMapper ivrVoiceMapper;
    @Resource
    private FileApi fileApi;

    @Resource
    private ExtendApi extendApi;
    @Resource
    private IvrFlowMapper ivrFlowMapper;

    @Resource
    private IvrRobotTimbreMapper ivrRobotTimbreMapper;
    @Resource
    private IvrTimbreMapper ivrTimbreMapper;

    @Override
    public List<JSONObject> ivrContentList(Long flowId) {
        IvrFlowDO ivrFlowDO = ivrFlowMapper.selectById(flowId);
        if (ivrFlowDO == null || StringUtils.isEmpty(ivrFlowDO.getFlowData())) {
            return null;
        }
        JSONObject flowJson = JSONUtil.parseObj(ivrFlowDO.getFlowData());
        JSONArray nodes = flowJson.getJSONArray("nodes");
        List<JSONObject> contentList = new ArrayList<>();
        for (Object node : nodes) {
            JSONObject nodeJson = JSONUtil.parseObj(node);
            if ("menu-node".equals(nodeJson.getStr("type"))||  "playback-node".equals(nodeJson.getStr("type"))) {
                if (StringUtils.isNotEmpty(nodeJson.getJSONObject("properties").getStr("content"))) {
                    JSONObject jsonResult = new JSONObject();
                    jsonResult.set("id", nodeJson.getStr("id"));
                    jsonResult.set("name", nodeJson.getJSONObject("properties").getStr("name"));
                    jsonResult.set("content", nodeJson.getJSONObject("properties").getStr("content"));
                    String filePath = nodeJson.getJSONObject("properties").getStr("filePath");
                    Long fileId  = nodeJson.getJSONObject("properties").getLong("fileId");
                    if (StringUtils.isEmpty(filePath) || fileId == null) {
                        jsonResult.set("isVoice", 0);
                    } else {
                        jsonResult.set("isVoice", 1);
                        IvrVoiceDO ivrVoiceDO = ivrVoiceMapper.selectById(fileId);
                        jsonResult.set("filePath", ivrVoiceDO.getFilePath());
                    }
                    contentList.add(jsonResult);
                }
            }
        }
        return contentList;
    }
    @Override
    public Long createVoiceList(IvrVoiceSaveReqVO createReqVO) {
        IvrFlowDO ivrFlowDO = ivrFlowMapper.selectById(createReqVO.getFlowId());
        if (ivrFlowDO == null || StringUtils.isEmpty(ivrFlowDO.getFlowData())) {
            return null;
        }
        //生成机器人音色
        LambdaQueryWrapper<IvrRobotTimbreDO> robotTimbreDOLambdaQueryWrapper = new LambdaQueryWrapper<>();
        robotTimbreDOLambdaQueryWrapper.eq(IvrRobotTimbreDO::getFlowId, createReqVO.getFlowId());
        robotTimbreDOLambdaQueryWrapper.last("limit 1");
        IvrRobotTimbreDO ivrRobotTimbreDORet = ivrRobotTimbreMapper.selectOne(robotTimbreDOLambdaQueryWrapper);
        if (ivrRobotTimbreDORet != null) {
            ivrRobotTimbreDORet.setVoiceType(createReqVO.getVoiceType());
            ivrRobotTimbreDORet.setVolumeRatio(Long.valueOf(createReqVO.getVolume()));
            ivrRobotTimbreDORet.setSpeedRatio(Long.valueOf(createReqVO.getSpeed()));
            ivrRobotTimbreMapper.updateById(ivrRobotTimbreDORet);
        } else {
            LambdaQueryWrapper<IvrTimbreDO> timbreDOLambdaQueryWrapper = new LambdaQueryWrapper<>();
            timbreDOLambdaQueryWrapper.eq(IvrTimbreDO::getTimbreId, createReqVO.getVoiceType());
            timbreDOLambdaQueryWrapper.last("limit 1");
            IvrTimbreDO ivrTimbreDO = ivrTimbreMapper.selectOne(timbreDOLambdaQueryWrapper);
            IvrRobotTimbreDO ivrRobotTimbreDO = new IvrRobotTimbreDO();
            ivrRobotTimbreDO.setVoiceType(createReqVO.getVoiceType());
            ivrRobotTimbreDO.setVolumeRatio(Long.valueOf(createReqVO.getVolume()));
            ivrRobotTimbreDO.setSpeedRatio(Long.valueOf(createReqVO.getSpeed()));
            ivrRobotTimbreDO.setFlowId(ivrFlowDO.getId());
            ivrRobotTimbreDO.setTimbreId(ivrTimbreDO.getId());
            ivrRobotTimbreMapper.insert(ivrRobotTimbreDO);
        }
        JSONObject flowJson = JSONUtil.parseObj(ivrFlowDO.getFlowData());
        for (Object node : flowJson.getJSONArray("nodes")) {
            JSONObject nodeJson = JSONUtil.parseObj(node);
            if ("menu-node".equals(nodeJson.getStr("type"))||  "playback-node".equals(nodeJson.getStr("type"))) {
                String filePath = nodeJson.getJSONObject("properties").getStr("filePath");
                if (StringUtils.isEmpty(filePath)) {
                    String content = nodeJson.getJSONObject("properties").getStr("content");
                    if  (StringUtils.isNotEmpty(content)) {
                        createReqVO.setContent(nodeJson.getJSONObject("properties").getStr("content"));
                        IvrVoiceSaveReqVO voice = createVoice(createReqVO);
                        nodeJson.getJSONObject("properties").set("filePath", voice.getLocalPath());
                        nodeJson.getJSONObject("properties").set("fileId", voice.getId());
                        nodeJson.getJSONObject("properties").set("playbackType", 1);
                    }

                }
            }
        }
        ivrFlowDO.setFlowData(flowJson.toString());
        ivrFlowMapper.updateById(ivrFlowDO);
        return null;
    }

    @Override
    public Long createVoiceByNodeId(IvrVoiceSaveReqVO createReqVO) {
        IvrFlowDO ivrFlowDO = ivrFlowMapper.selectById(createReqVO.getFlowId());
        if (ivrFlowDO == null || StringUtils.isEmpty(ivrFlowDO.getFlowData())) {
            return null;
        }
        JSONObject flowJson = JSONUtil.parseObj(ivrFlowDO.getFlowData());
        JSONArray nodes = flowJson.getJSONArray("nodes");
        if (nodes == null || nodes.isEmpty()) {
            return null; // 提前返回，避免空指针
        }
        for (Object node : nodes) {
            JSONObject nodeJson = JSONUtil.parseObj(node);
            String type = nodeJson.getStr("type");
            if (!"menu-node".equals(type) && !"playback-node".equals(type)) {
                continue; // 跳过非目标类型节点
            }
            JSONObject properties = nodeJson.getJSONObject("properties");
            if (properties == null) {
                continue;
            }
            String nodeId = nodeJson.getStr("id");
            String content = properties.getStr("content");
            String filePath = properties.getStr("filePath");
            // 只处理内容存在且节点ID匹配的情况
            if (StringUtils.isNotEmpty(content) && nodeId.equals(createReqVO.getNodeId())) {
                createReqVO.setContent(content);
                IvrVoiceSaveReqVO voice = createVoice(createReqVO);

                // 更新属性
                properties.set("filePath", voice.getLocalPath());
                properties.set("fileId", voice.getId());
                properties.set("playbackType", 1);
            }
        }
        ivrFlowDO.setFlowData(flowJson.toString());
        ivrFlowMapper.updateById(ivrFlowDO);
        return null;
    }
    @Override
    public Long createVoiceByNodeIdManual(IvrVoiceSaveReqVO createReqVO) {
        IvrFlowDO ivrFlowDO = ivrFlowMapper.selectById(createReqVO.getFlowId());
        if (ivrFlowDO == null || StringUtils.isEmpty(ivrFlowDO.getFlowData())) {
            return null;
        }
        JSONObject flowJson = JSONUtil.parseObj(ivrFlowDO.getFlowData());
        JSONArray nodes = flowJson.getJSONArray("nodes");
        if (nodes == null || nodes.isEmpty()) {
            return null; // 提前返回，避免空指针
        }
        for (Object node : nodes) {
            JSONObject nodeJson = JSONUtil.parseObj(node);
            String type = nodeJson.getStr("type");
            if (!"menu-node".equals(type) && !"playback-node".equals(type)) {
                continue; // 跳过非目标类型节点
            }
            JSONObject properties = nodeJson.getJSONObject("properties");
            if (properties == null) {
                continue;
            }
            String nodeId = nodeJson.getStr("id");
            String content = properties.getStr("content");
            // 只处理内容存在且节点ID匹配的情况
            if (StringUtils.isNotEmpty(content) && nodeId.equals(createReqVO.getNodeId())) {
                createReqVO.setContent(content);
                try {
                    IvrVoiceSaveReqVO voice = createVoiceManual(createReqVO);
                    // 更新属性
                    properties.set("filePath", voice.getLocalPath());
                    properties.set("fileId", voice.getId());
                    properties.set("playbackType", 1);
                    ivrFlowDO.setFlowData(flowJson.toString());
                    ivrFlowMapper.updateById(ivrFlowDO);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        }
        return null;
    }

    @Override
    public Long delVoiceList(Long flowId) {
        IvrFlowDO ivrFlowDO = ivrFlowMapper.selectById(flowId);
        if (ivrFlowDO == null || StringUtils.isEmpty(ivrFlowDO.getFlowData())) {
            return null;
        }
        JSONObject flowJson = JSONUtil.parseObj(ivrFlowDO.getFlowData());
        for (Object node : flowJson.getJSONArray("nodes")) {
            JSONObject nodeJson = JSONUtil.parseObj(node);
            if ("menu-node".equals(nodeJson.getStr("type"))||  "playback-node".equals(nodeJson.getStr("type"))) {
                nodeJson.getJSONObject("properties").set("filePath", "");
                nodeJson.getJSONObject("properties").set("fileId", null);
                nodeJson.getJSONObject("properties").set("playbackType", 2);
            }
        }
        ivrFlowDO.setFlowData(flowJson.toString());
        ivrFlowMapper.updateById(ivrFlowDO);
        return null;
    }
    @Override
    public Long upDateIvrContentByNodeId(IvrFlowNodeVO updateReqVO) {

        IvrFlowDO ivrFlowDO = ivrFlowMapper.selectById(updateReqVO.getFlowId());
        if (ivrFlowDO == null || StringUtils.isEmpty(ivrFlowDO.getFlowData())) {
            return null;
        }
        JSONObject flowJson = JSONUtil.parseObj(ivrFlowDO.getFlowData());
        for (Object node : flowJson.getJSONArray("nodes")) {
            JSONObject nodeJson = JSONUtil.parseObj(node);
            if ("menu-node".equals(nodeJson.getStr("type")) || "playback-node".equals(nodeJson.getStr("type"))) {
                if (updateReqVO.getNodeId().equals(nodeJson.getStr("id"))) {
                    nodeJson.getJSONObject("properties").set("content", updateReqVO.getContent());
                    nodeJson.getJSONObject("properties").set("filePath", "");
                    nodeJson.getJSONObject("properties").set("fileId", null);
                    nodeJson.getJSONObject("properties").set("playbackType", 2);
                }
            }
        }
        ivrFlowDO.setFlowData(flowJson.toString());
        ivrFlowMapper.updateById(ivrFlowDO);
        return null;
    }
    @Override
    public Long delVoiceByNodeId(Long flowId, String nodeId) {
        IvrFlowDO ivrFlowDO = ivrFlowMapper.selectById(flowId);
        if (ivrFlowDO == null || StringUtils.isEmpty(ivrFlowDO.getFlowData())) {
            return null;
        }
        JSONObject flowJson = JSONUtil.parseObj(ivrFlowDO.getFlowData());
        for (Object node : flowJson.getJSONArray("nodes")) {
            JSONObject nodeJson = JSONUtil.parseObj(node);
            if ("menu-node".equals(nodeJson.getStr("type"))||  "playback-node".equals(nodeJson.getStr("type"))) {
                if (nodeId.equals(nodeJson.getStr("id"))) {
                    nodeJson.getJSONObject("properties").set("filePath", "");
                    nodeJson.getJSONObject("properties").set("fileId", null);
                    nodeJson.getJSONObject("properties").set("playbackType", 2);
                }
            }
        }
        ivrFlowDO.setFlowData(flowJson.toString());
        ivrFlowMapper.updateById(ivrFlowDO);
        return null;
    }


    //试听
    @Override
    public IvrVoiceSaveReqVO audition(IvrVoiceSaveReqVO createReqVO) {
        if (null == createReqVO.getTimbreType() || createReqVO.getTimbreType() == 1) {
            byte[] baiDuTtsByte = TtsUtil.getKeDaXunFeiTtsBasicUrlNew(createReqVO.getContent(), createReqVO.getVoiceType(), createReqVO.getSpeed(), createReqVO.getVolume(), createReqVO.getPitch());
            String baiDuTtsByteString = Base64.getEncoder().encodeToString(baiDuTtsByte);
            Map<String, Object> params = new HashMap<String, Object>() {{
                put("ttsByte", baiDuTtsByteString);
                put("type", "tts");
            }};
            extendApi.setDomain");
            JSONObject agentState = extendApi.request("/index/pcmToWave", JSONUtil.toJsonStr(params));
            String filePath = agentState.getStr("filePath");
            String localPath = agentState.getStr("localPath");
            createReqVO.setFilePath(filePath);
            createReqVO.setLocalPath(localPath);
        }
        if (null != createReqVO.getTimbreType() && createReqVO.getTimbreType() == 2) {
//            byte[] baiDuTtsByte = TtsUtil.getHuoShanTtsBasicUrlNew(createReqVO.getContent(), createReqVO.getVoiceType(), createReqVO.getSpeed(), createReqVO.getVolume(), createReqVO.getPitch());
            byte[] baiDuTtsByte = null;
            try {
                baiDuTtsByte = TtsHuoShanUtil.synthesizeTTS(createReqVO.getContent(), createReqVO.getVoiceType(), createReqVO.getSpeed(), createReqVO.getVolume());
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            String base64String = encodeToBase64(baiDuTtsByte);
            // 输出 Base64 字符串
            String content = TmtUtil.tengXunTmt(base64String);
            createReqVO.setContent(content);
            Map<String, Object> params = new HashMap<String, Object>() {{
                put("byte", base64String);
                put("type", "file");
            }};
            extendApi.setDomain("https://scrmextend.com:8082");
            JSONObject agentState = extendApi.request("/index/ivrUpload", JSONUtil.toJsonStr(params));
            String filePath = agentState.getStr("filePath");
            String localPath = agentState.getStr("localPath");
            createReqVO.setFilePath(filePath);
            createReqVO.setLocalPath(localPath);
        }
        return createReqVO;
    }

    private IvrVoiceSaveReqVO createVoice(IvrVoiceSaveReqVO createReqVO) {
        if (null == createReqVO.getTimbreType() || createReqVO.getTimbreType() == 1) {
            byte[] baiDuTtsByte = TtsUtil.getKeDaXunFeiTtsBasicUrlNew(createReqVO.getContent(), createReqVO.getVoiceType(),createReqVO.getSpeed(),createReqVO.getVolume(),createReqVO.getPitch());
            String baiDuTtsByteString = Base64.getEncoder().encodeToString(baiDuTtsByte);
            Map<String, Object> params = new HashMap<String, Object>() {{
                put("ttsByte", baiDuTtsByteString);
                put("type", "tts");
            }};
            extendApi.setDomain("https://scrmextend.com:8082");
            JSONObject agentState = extendApi.request("/index/pcmToWave", JSONUtil.toJsonStr(params));
            String filePath = agentState.getStr("filePath");
            String localPath = agentState.getStr("localPath");
            createReqVO.setFilePath(filePath);
            createReqVO.setLocalPath(localPath);
            createReqVO.setName(createReqVO.getContent());
            createReqVO.setId(null);
            IvrVoiceDO ivrVoice = BeanUtils.toBean(createReqVO, IvrVoiceDO.class);
            ivrVoiceMapper.insert(ivrVoice);
            createReqVO.setId(ivrVoice.getId());
            extendApi.setDomain("https://127.0.0.1:8082");
            extendApi.clearMatchCache(ivrVoice.getId());
        }
        if (null != createReqVO.getTimbreType() && createReqVO.getTimbreType() == 2) {
//            byte[] baiDuTtsByte = TtsUtil.getHuoShanTtsBasicUrlNew(createReqVO.getContent(), createReqVO.getVoiceType(), createReqVO.getSpeed(), createReqVO.getVolume(), createReqVO.getPitch());
            byte[] baiDuTtsByte = null;
            try {
                baiDuTtsByte = TtsHuoShanUtil.synthesizeTTS(createReqVO.getContent(), createReqVO.getVoiceType(), createReqVO.getSpeed(), createReqVO.getVolume());
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

            String base64String = encodeToBase64(baiDuTtsByte);
            // 输出 Base64 字符串
            String content = TmtUtil.tengXunTmt(base64String);
            createReqVO.setContent(content);
            Map<String, Object> params = new HashMap<String, Object>() {{
                put("byte", base64String);
                put("type", "file");
            }};
            extendApi.setDomain("https://scrmextend.com:8082");
            JSONObject agentState = extendApi.request("/index/ivrUpload", JSONUtil.toJsonStr(params));
            String filePath = agentState.getStr("filePath");
            String localPath = agentState.getStr("localPath");
            createReqVO.setFilePath(filePath);
            createReqVO.setLocalPath(localPath);
            createReqVO.setName(createReqVO.getContent());
            createReqVO.setId(null);
            IvrVoiceDO ivrVoice = BeanUtils.toBean(createReqVO, IvrVoiceDO.class);
            ivrVoiceMapper.insert(ivrVoice);
            System.out.println("ivrVoice:"+ivrVoice.getId());
            createReqVO.setId(ivrVoice.getId());
            extendApi.setDomain("https://127.0.0.1:8082");
            extendApi.clearMatchCache(ivrVoice.getId());
        }


        return createReqVO;
    }


    private IvrVoiceSaveReqVO createVoiceManual(IvrVoiceSaveReqVO createReqVO) {
        byte[] baiDuTtsByte = null;
        try {
            baiDuTtsByte = mp3ToWavByteArray(createReqVO.getFile());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        String base64String = encodeToBase64(baiDuTtsByte);
        Map<String, Object> params = new HashMap<String, Object>() {{
            put("byte", base64String);
            put("type", "file");
        }};
        extendApi.setDomain("https://127.0.0.1:8082");
        JSONObject agentState = extendApi.request("/index/ivrUpload", JSONUtil.toJsonStr(params));
        String filePath = agentState.getStr("filePath");
        String localPath = agentState.getStr("localPath");
        createReqVO.setFilePath(filePath);
        createReqVO.setLocalPath(localPath);
        IvrVoiceDO ivrVoice = BeanUtils.toBean(createReqVO, IvrVoiceDO.class);
        ivrVoiceMapper.insert(ivrVoice);
        createReqVO.setId(ivrVoice.getId());
        extendApi.setDomain("https://127.0.0.1:8082");
        extendApi.clearMatchCache(ivrVoice.getId());
        return createReqVO;
    }
    @Override
    public Long createIvrVoice(IvrVoiceSaveReqVO createReqVO) {
        if (1 != createReqVO.getType()) {//合成
            if (StringUtils.isEmpty(createReqVO.getContent())) {
                throw exception(IVR_VOICE_CONTENT_NOT_EXISTS);
            }
//            byte[] baiDuTtsByte = TtsUtil.getTengXunTtsUrl(createReqVO.getContent(), createReqVO.getVoiceType());
//            byte[] baiDuTtsByte = TtsUtil.getTengXunTtsBasicUrl(createReqVO.getContent(), createReqVO.getVoiceType());
            if (null == createReqVO.getTimbreType() || createReqVO.getTimbreType() == 1) {
                byte[] baiDuTtsByte = TtsUtil.getKeDaXunFeiTtsBasicUrl(createReqVO.getContent(), createReqVO.getVoiceType());
                String baiDuTtsByteString = Base64.getEncoder().encodeToString(baiDuTtsByte);
                Map<String, Object> params = new HashMap<String, Object>() {{
                    put("ttsByte", baiDuTtsByteString);
                    put("type", "tts");
                }};
                extendApi.setDomain("http://127.0.0.1:8082");
                JSONObject agentState = extendApi.request("/index/pcmToWave", JSONUtil.toJsonStr(params));
                String filePath = agentState.getStr("filePath");
                String localPath = agentState.getStr("localPath");
//            byte[] decode = Base64.getDecoder().decode(ttsByteRetStr);
////            String aaa = Base64.getEncoder().encodeToString(Base64.getDecoder().decode(ttsByteRetStr));
//            String file1 = fileApi.createFile(createReqVO.getName() + UUID.randomUUID().toString() + ".wav", UUID.randomUUID().toString() + ".wav", decode);
                createReqVO.setFilePath(filePath);
                createReqVO.setName(createReqVO.getContent());
                createReqVO.setLocalPath(localPath);
            }
            if (null != createReqVO.getTimbreType() && createReqVO.getTimbreType() == 2) {
//                byte[] baiDuTtsByte = TtsUtil.getHuoShanTtsBasicUrlNew(createReqVO.getContent(), createReqVO.getVoiceType(), createReqVO.getSpeed(), createReqVO.getVolume(), createReqVO.getPitch());
                byte[] baiDuTtsByte = null;
                try {
                    baiDuTtsByte = TtsHuoShanUtil.synthesizeTTS(createReqVO.getContent(), createReqVO.getVoiceType(), createReqVO.getSpeed(), createReqVO.getVolume());
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                String base64String = encodeToBase64(baiDuTtsByte);
                // 输出 Base64 字符串
                String content = TmtUtil.tengXunTmt(base64String);
                createReqVO.setContent(content);
                createReqVO.setName(content);
                Map<String, Object> params = new HashMap<String, Object>() {{
                    put("byte", base64String);
                    put("type", "file");
                }};
                extendApi.setDomain("https://scrmextend.com:8082");
                JSONObject agentState = extendApi.request("/index/ivrUpload", JSONUtil.toJsonStr(params));
                String filePath = agentState.getStr("filePath");
                String localPath = agentState.getStr("localPath");
                createReqVO.setFilePath(filePath);
                createReqVO.setLocalPath(localPath);
            }

        } else {//手动
            String remoteFileUrl = createReqVO.getFilePath(); // 远程文件的 URL
            try {
                // 获取文件的输入流
                InputStream inputStream = getFileFromUrl(remoteFileUrl);
                // 将文件转换为字节数组
                byte[] fileBytes = convertStreamToBytes(inputStream);
                // 将字节数组转换为 Base64 字符串
                String base64String = encodeToBase64(fileBytes);
                // 输出 Base64 字符串
                String content = TmtUtil.tengXunTmt(base64String);
                createReqVO.setContent(content);
                createReqVO.setName(content);
                Map<String, Object> params = new HashMap<String, Object>() {{
                    put("byte", base64String);
                    put("type", "file");
                }};
                extendApi.setDomain("http://scrmextend.com:8081");
                JSONObject agentState = extendApi.request("/index/ivrUpload", JSONUtil.toJsonStr(params));
                String filePath = agentState.getStr("filePath");
                String localPath = agentState.getStr("localPath");
                createReqVO.setFilePath(filePath);
                createReqVO.setLocalPath(localPath);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // 插入
        IvrVoiceDO ivrVoice = BeanUtils.toBean(createReqVO, IvrVoiceDO.class);
        ivrVoiceMapper.insert(ivrVoice);
        // 返回
        return ivrVoice.getId();
    }
    // 从 URL 获取文件输入流
    private static InputStream getFileFromUrl(String fileUrl) throws Exception {
        URL url = new URL(fileUrl);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");
        connection.setConnectTimeout(5000); // 设置连接超时时间
        connection.setReadTimeout(5000);    // 设置读取超时时间
        return connection.getInputStream();
    }

    // 将输入流转换为字节数组
    private static byte[] convertStreamToBytes(InputStream inputStream) throws Exception {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int bytesRead;

        while ((bytesRead = inputStream.read(buffer)) != -1) {
            byteArrayOutputStream.write(buffer, 0, bytesRead);
        }
        return byteArrayOutputStream.toByteArray();
    }
    // 将字节数组编码为 Base64 字符串
    private static String encodeToBase64(byte[] data) {
        return Base64.getEncoder().encodeToString(data);
    }
    @Override
    public void updateIvrVoice(IvrVoiceSaveReqVO updateReqVO) {
        // 校验存在
        validateIvrVoiceExists(updateReqVO.getId());
        // 更新
        IvrVoiceDO updateObj = BeanUtils.toBean(updateReqVO, IvrVoiceDO.class);
        ivrVoiceMapper.updateById(updateObj);
    }

    @Override
    public void deleteIvrVoice(Long id) {
        // 校验存在
        validateIvrVoiceExists(id);
        // 删除
        ivrVoiceMapper.deleteById(id);
    }

    private void validateIvrVoiceExists(Long id) {
        if (ivrVoiceMapper.selectById(id) == null) {
            throw exception(IVR_VOICE_NOT_EXISTS);
        }
    }

    @Override
    public IvrVoiceDO getIvrVoice(Long id) {
        return ivrVoiceMapper.selectById(id);
    }

    @Override
    public PageResult<IvrVoiceDO> getIvrVoiceList(IvrVoicePageReqVO pageReqVO) {
        return ivrVoiceMapper.selectPage(pageReqVO);
    }

    public List<IvrVoiceDO> getIvrVoiceList() {
        return ivrVoiceMapper.selectList();
    }

    public static byte[] mp3ToWavByteArray(MultipartFile mp3File) throws Exception {
        String originalFilename = mp3File.getOriginalFilename();
        if (originalFilename == null || !originalFilename.contains(".")) {
            throw new IllegalArgumentException("Invalid file name.");
        }
        String suffix = originalFilename.substring(originalFilename.lastIndexOf(".")).toLowerCase();
        // 如果是 .wav 文件，直接返回 byte[]
        if (".wav".equals(suffix)) {
            try {
                return mp3File.getBytes();
            } catch (IOException e) {
                throw new RuntimeException("Failed to read the content of the WAV file.", e);
            }
        }
        // 将 MultipartFile 转换为 InputStream
        InputStream mp3InputStream = mp3File.getInputStream();

        // 使用 BufferedInputStream 以确保支持 mark/reset
        BufferedInputStream bufferedInputStream = new BufferedInputStream(mp3InputStream);

        // 获取音频输入流
        AudioInputStream mp3AudioStream = AudioSystem.getAudioInputStream(bufferedInputStream);

        // 获取音频格式
        AudioFormat baseFormat = mp3AudioStream.getFormat();

        // 定义目标音频格式
        AudioFormat targetFormat = new AudioFormat(
                AudioFormat.Encoding.PCM_SIGNED,
                baseFormat.getSampleRate(),
                16,  // 16-bit PCM
                baseFormat.getChannels(),
                baseFormat.getChannels() * 2,  // 每通道字节数
                baseFormat.getSampleRate(),
                false  // 不使用大端字节序
        );

        // 转换为 PCM 格式
        AudioInputStream pcmAudioStream = AudioSystem.getAudioInputStream(targetFormat, mp3AudioStream);

        // 写入 ByteArrayOutputStream
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
            // 使用 AudioSystem 将 PCM 格式音频流写入 WAV 格式并返回字节数组
            AudioSystem.write(pcmAudioStream, AudioFileFormat.Type.WAVE, baos);
            return baos.toByteArray();
        } catch (Exception e) {
            // 打印日志或抛出自定义异常
            System.err.println("[mp3ToWavByteArray] 转换失败: " + e.getMessage());
            e.printStackTrace();
            return null;
        } finally {
            // 确保流被关闭
            if (mp3AudioStream != null) {
                try {
                    mp3AudioStream.close();
                } catch (IOException e) {
                    System.err.println("[mp3ToWavByteArray] 关闭 mp3AudioStream 失败: " + e.getMessage());
                }
            }
            if (pcmAudioStream != null) {
                try {
                    pcmAudioStream.close();
                } catch (IOException e) {
                    System.err.println("[mp3ToWavByteArray] 关闭 pcmAudioStream 失败: " + e.getMessage());
                }
            }
        }
    }
}